from .server import P2PServer
from .client import P2PClient

class P2PNetNode(object):
    """
    Py2P main class, which handles the network
    interaction and provides general peer to peer
    functionalities
    """
    
    def __init__(self, onreceive=None, onconnect=None, onclose=None):
        """
        initialize the class members as necessary
        """
        
        self.started = False
        self.port = None
        self.server = None;
        self.hosts = []
        
        self.onreceive = onreceive
        self.onconnect = onconnect
        self.onclose = onclose
    
    #def __client_sent_data(self, address: str, data: str):
    def __client_sent_data(self, address, data):
        if not self.onreceive is None:
            self.onreceive(address)
    
    #def __client_connected(self, address: str, targetsend):
    def __client_connected(self, address, targetsend):
        self.connections[address] = {"send" : targetsend}
        if not self.onconnect is None:
            self.onconnect(address)
    
    #def __client_closed(self, address: str):
    def __client_closed(self, address):
        self.connections.pop(address)
        if not self.onclose is None:
            self.onclose(address)
    
    
    #def start(self, port: int):
    def start(self, port):
        """
        start network communication on the
        specified port
        """
        
        self.port = port
        # create our p2p server
        self.server = P2PServer(onreceive=self.__client_sent_data,
                                onconnect=self.__client_connected,
                                onclose=self.__client_closed)
        # create our p2p client
        self.client = P2PClient(onreceive=self.__client_sent_data,
                                onconnect=self.__client_connected,
                                onclose=self.__client_closed)
        # start connections
        self.server.start(self.port)
        self.client.start(self.port)
        # set started state True
        self.started = True
    
    def stop(self):
        """
        stop all network communication
        """
        
        # stop accepting connections
        self.server.stop()
        self.client.stop()
        # set started state False
        self.started = False
    
    #def connect(self, address: str):
    def connect(self, address):
        """
        connect to another node
        """
        
        # check if the we already started
        if self.started == False:
            raise
        
        # check if the node is already connected, otherwise connect
        if not self.is_connected(address=address):
            self.connect(address=address)
    
    #def close(self, address: str):
    def close(self, address):
        """
        disconnect from a connected node
        """
        
        # check if the we already started
        if self.started == False:
            raise
        
        # loop through all hosts
        for host in self.hosts:
            if host.clienhost == address:
                # close the connection
                host.close()
                # remove the connection from the list
                # should be removed automatically, as the targetclosed
                # function is called immediately
                #self.hosts.remove(host)
    
    #def is_connected(self, address: str):
    def is_connected(self, address):
        """
        checks if a node with the specified address
        is already connected
        """
        
        # check if the we already started
        if self.started == False:
            raise
        
        if self.server.contains(address) or self.client.contains(address):
            return True
        else:
            return False
    
    #def send(self, address: str, data: str):
    def send(self, address, data):
        """
        send data to a specific node
        """
        
        # check if the server is running
        if self.started == False:
            raise
        
        # send the data
        targetsend = self.connections[address]["send"]
        targetsend(address, data)
    
